In this tutorial we will see how to generate PWM using PWM module in PIC16F616
PIC16F616 has CCP module(Capture compare PWM module) which can be used to count frequency of input signal or use inbuilt comparator or generate PWM.
#include <xc.h>
// CONFIG
#pragma config FOSC = INTOSCIO // Oscillator Selection bits (INTOSCIO oscillator: I/O function on RA4/OSC2/CLKOUT pin, I/O function on RA5/OSC1/CLKIN)
#pragma config WDTE = OFF // Watchdog Timer Enable bit (WDT disabled and can be enabled by SWDTEN bit of the WDTCON register)
#pragma config PWRTE = OFF // Power-up Timer Enable bit (PWRT disabled)
#pragma config MCLRE = ON // MCLR Pin Function Select bit (MCLR pin function is MCLR)
#pragma config CP = OFF // Code Protection bit (Program memory code protection is disabled)
#pragma config IOSCFS = 8MHZ // Internal Oscillator Frequency Select bit (8 MHz)
#pragma config BOREN = OFF // Brown-out Reset Selection bits (BOR Disabled)
#define Tout RA0
unsigned long int PWM_freq = 8000UL; // min freq achievable is 4khz
unsigned int duty_cycle = 816,result;
unsigned char T0_count,T1H_count,T1L_count;
_Bool check1,check2;
//unsigned int off_count_calculator();
void __interrupt () ISR(void)
{
//PORTAbits.RA4 = 1;
if(TMR0IF)
{
T0IE = 0;
TMR0IF = 0;
//PORTAbits.RA4 = 1;
Tout = 1U;
//Tout = check1;
//check1 = !check1;
TMR0 = T0_count;
TMR1L = T1L_count;
TMR1H = T1H_count;
T0IE = 1;
TMR1IE = 1;
}
if(TMR1IF)
{
TMR1IE = 0;
TMR1IF = 0;
Tout = 0U;
}
if(ADIF)
{
ADIE = 0; // disable adc interrupt
ADIF = 0; // clear adc interrupt flag
if(!GO) // if conversion is complete
{
result = ADRESH;
result = (result<<8) + ADRESL;
//GO = 1;
}
ADIE = 1; // enable adc interrupt
}
}
void ADC2_init()
{
ADIE = 0U;
ADIF = 0U;
ADFM = 1U; // right justified and vdd for analog voltage reference
ADCON0 &= 0x1B; // select channel2 for adc conversion
ADIE = 1;
}
void PWM_init(uint32_t freq)
{
uint8_t factor,i,temp;
//GPIO_create(PORTC, 5, input, FALSE);
GPIO_create(PORTC, 5, digital_output, FALSE);
factor = (((cpu_clk>>2)/freq)/0xFF);
if(factor == 0)
{
PR2 = (((cpu_clk>>2)/freq) - 1);
T2CONbits.T2CKPS = 0U;
}
else if(factor < 4)
{
PR2 = (((cpu_clk>>4)/freq) - 1);
T2CONbits.T2CKPS = 1U;
}
else
{
PR2 = (((cpu_clk>>6)/freq) - 1);
T2CONbits.T2CKPS = 2U;
}
//PR2 = 0x50;
temp = PR2;
for(i = 0; i < 8; i++)
{
temp = temp>>1;
if(!temp)
break;
res++;
}
CCP1CONbits.PM = 0;
CCP1CONbits.CCP1M = 0xC;
CCPR1L = (PR2>>1);
CCP1CONbits.DCB = 3;
PIE1bits.TMR2IE = 0U;
PIR1bits.T2IF = 0U;
PIE1bits.T2IE = 1U;
T2CONbits.TMR2ON = 1;
PIR1bits.T2IF = 0;
}
void main()
{
unsigned char count1 = 0,count2 = 4;
INTCONbits.GIE = 1;
INTCONbits.PEIE = 1;
ADC2_init();
while(1)
{
}
}